﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Plugin
{
    public class MapReader
    {
        private string pluginName;
        private string mapFileName;
        public Dictionary<string, HashSet<string>> streetCityDict { get; private set; }
        private string lastCity = "";
        private FileStream fs;
        public MapReader(string pluginName, string mapFileName, Dictionary<string, HashSet<string>> streetCityDict)
        {
            this.pluginName = pluginName;
            this.mapFileName = mapFileName;
            this.streetCityDict = streetCityDict;
        }
        public void Run()
        {
            //Dictonary leeren
            streetCityDict.Clear();

            try
            {
                string filePath = "Plugins\\" + pluginName + '\\' + mapFileName;
                Update(filePath);
            }
            catch (FileNotFoundException)
            {
                /* Datei wurde im laufenden Betrieb entfernt. Darf nicht passieren. */
                Console.WriteLine("Error: Navigations-Plugin\nDie Datei " + mapFileName + " ist nicht vorhanden.");
            }
            catch (Exception ex)
            {
                /* Ein anderer Fehler ist aufgetreten. */
                Console.WriteLine("Error: Navigations-Plugin\nDetails:" + ex.Message);
            }
            finally
            {
                Plugin.aufbereitungLaeuft = false;
                if (fs != null)
                    fs.Close();
            }
        }
        public int GetPercentOfFileStream()
        {
            if (Plugin.aufbereitungLaeuft)
            {
                if (fs == null)
                {
                    return -1;
                }
                else
                {
                    float pos = fs.Position;
                    float len = fs.Length;
                    float div = (pos / len)*100;
                    return (int)div;
                }
            }
            else
            {
                return 100;
            }
        }
        public void Update(string file)
        {
            fs = File.OpenRead(file);
            var xml = new System.Xml.XmlTextReader(fs);
            while (xml.Read())
            {
                if (xml.NodeType == System.Xml.XmlNodeType.Element && xml.Name == "osm")
                {
                    ReadOsm(xml);
                }
            }
        }
        private void ReadOsm(System.Xml.XmlTextReader xml)
        {
            var osm = xml.ReadSubtree();
            while (osm.Read())
            {
                if (osm.NodeType == System.Xml.XmlNodeType.Element && (osm.Name == "node" || osm.Name == "way"))
                {
                    ReadAnyOsmElement(osm);
                }
            }
        }
        private void ReadAnyOsmElement(System.Xml.XmlReader osm)
        {
            var element = osm.ReadSubtree();
            while (element.Read())
            {
                if (element.NodeType == System.Xml.XmlNodeType.Element && element.Name == "tag")
                {
                    ReadTag(element);
                }
            }
        }
        private void ReadTag(System.Xml.XmlReader element)
        {
            string tagType = element.GetAttribute("k");
            string value = element.GetAttribute("v");
            switch (tagType)
            {
                case "addr:city":
                    lastCity = value;
                    break;
                case "addr:street":
                    if (streetCityDict.ContainsKey(value))
                    {
                        HashSet<string> hset = streetCityDict[value];
                        hset.Add(lastCity);
                    }
                    else
                    {
                        HashSet<string> hset = new HashSet<string>();
                        hset.Add(lastCity);
                        streetCityDict.Add(value, hset);
                    }
                    break;
            }
        }
    }
}
